const Service = require('egg').Service;
const Moment = require('moment');

class UserService extends Service {

  // 查看活动是否开启
  async getOpenid(code) {
    const { ctx, app } = this;
    const { appid, secret } = app.config.weixin;

    const res = await ctx.curl(`https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${code}&grant_type=authorization_code`, {
      dataType: 'json', timeout: 20000
    });
    const data = res.data;
    app.assetWeixinResult(data);
    return data;
  }

  async refreshAccessToken() {
    const { ctx, app } = this;
    const { mysql } = app;
    const { appid, secret } = app.config.weixin;
    const res = await ctx.curl(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, {
      dataType: 'json', timeout: 5000
    });
    const data = res.data;
    app.assetWeixinResult(data);
    const { access_token, expires_in } = data;

    const expires_in_time = Moment();
    expires_in_time.add(expires_in, 's');
    await mysql.update('jiaolan_token', {
      access_token, expires_in: expires_in_time.toDate()
    }, {
      where: {
        token_id: 1
      }
    });
    return access_token;

  }

  async getAccessToken() {
    const { ctx, app } = this;
    const { appid, secret } = app.config.weixin;
    const { mysql } = app;
    let { access_token, expires_in } = await mysql.get('jiaolan_token', {
      token_id: 1
    });

    const expires_in_date = Moment(expires_in);
    if (Moment()
      .isAfter(expires_in_date)) {
      access_token = await ctx.service.user.refreshAccessToken();
    }

    return access_token;

  }

  async get_phone(code) {
    const { ctx, app } = this;
    const access_token = await this.getAccessToken();
    const res = await ctx.curl(`https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=${access_token}`, {
      dataType: 'json', timeout: 5000, method: 'POST', contentType: 'json', data: {
        code
      }
    });
    const { data } = res;
    app.assetWeixinResult(data);
    const { phone_info } = data;
    return phone_info;

  }

  async transUserInfo(info) {
    const { app } = this;
    const { mysql } = app;

    let userinfo = info;
    if (userinfo.date) {
      userinfo.date = Moment(userinfo.date)
        .format('YYYY-MM-DD');
    }

    return userinfo;
  }

  async initUser({ openid }) {
    const { app } = this;
    const { mysql } = app;
    const { channel } = this.ctx.request.body;
    let userInfo = await mysql.get('jiaolan_user', {
      openid
    });
    if (!userInfo) {

      await mysql.insert('jiaolan_user', {
        openid,
        channel
      });

      userInfo = await mysql.get('jiaolan_user', {
        openid
      });

    }

    return this.transUserInfo(userInfo);

  }

  async get_userinfo(openid) {
    const { mysql } = this.app;
    const userInfo = await mysql.get('jiaolan_user', {
      openid
    });
    if (!userInfo) {
      throw new Error('找不到用户');
    }

    return this.transUserInfo(userInfo);

  }

  async reserve(data) {
    const { city_id, date, scene_id, openid } = data;
    const { mysql } = this.app;
    const app = this.app;
    const active = await mysql.get('jiaolan_active', {
      open: 1
    });
    if (!active) throw new Error('没有开启的活动');
    let userinfo = await mysql.get('jiaolan_user', {
      openid
    });
    if (!userinfo) throw new Error('用户不存在');
    //if (userinfo.user_phone) throw new Error('您已经预约了')

    const cityInfo = await mysql.get('jiaolan_city', {
      city_id
    });
    if (!cityInfo) throw new Error('城市不存在');
    const { start_date, end_date } = cityInfo;
    const reserveDate = Moment(date);
    if (reserveDate.isBefore(start_date) || reserveDate.isAfter(end_date)) {
      throw new Error('无效的日期');
    }

    const sceneInfo = await mysql.get('jiaolan_scene', {
      scene_id
    });
    if (!sceneInfo) throw new Error('场次不存在');

    const conn = await mysql.beginTransaction();
    try {
      const yiyuyue = await conn.query('select count(1) as count from jiaolan_user where city_id = ? and date = ? and scene_id = ? for update', [
        city_id, date, scene_id
      ]);
      if (yiyuyue[0].count >= active.max) throw new Error('该场次已约满');
      await conn.update('jiaolan_user', {
        city_id,
        active_id: active.active_id,
        city_name: data.city_name,
        date,
        date_name: data.date_name,
        scene_id,
        scene_name: data.scene_name,
        user_name: data.user_name,
        user_phone: data.user_phone,
        sms_status: 1,
        reserve_time: new Date()
      }, {
        where: {
          openid
        }
      });

      await conn.commit(); // 提交事务
    } catch (ex) {
      await conn.rollback(); // 一定记得捕获异常后回滚事务！！
      throw ex;
    }

    userinfo = await mysql.get('jiaolan_user', {
      openid
    });
    app.runSchedule('sendSms');
    return userinfo;
  }

  async writeOff(openid) {
    const { mysql } = this.app;

    const userinfo = await mysql.get('jiaolan_user', {
      openid
    });

    if (userinfo.hasWriteOff) {
      throw new Error('您已经核销');
    }
    await mysql.update('jiaolan_user', {
      hasWriteOff: new Date(),
    }, {
      where: {
        openid
      }
    });
    userinfo.hasWriteOff = Moment()
      .format('YYYY-MM-DD');
    return userinfo;

  }

  async sendSms888(userInfo) {
    const { mysql } = this.app;
    const ctx = this.ctx;
    const cityInfo = await mysql.get('jiaolan_city', {
      city_id: userInfo.city_id
    });
    const parData = {
      sj: userInfo.user_phone,
      s1: encodeURIComponent(userInfo.user_name),
      s2: encodeURIComponent(cityInfo.city_sms),
      s3: `${userInfo.date_name}${userInfo.scene_name}`,
      s4: encodeURIComponent(cityInfo.sms_address)
    };
    ctx.logger.info('发送短信', userInfo.user_phone, userInfo.user_name, cityInfo.city_sms, userInfo.date_name, userInfo.scene_name, cityInfo.sms_address);
    const params = `sj=${parData.sj}&s1=${parData.s1}&s2=${parData.s2}&s3=${parData.s3}&s4=${parData.s4}`;
    const res = await ctx.curl(`https://shyb888.cn/11022/?action=J-086-241128&${params}`, {
      dataType: 'json'
    });
    ctx.logger.info('短信结果', res.data);
    if (res.data.code !== '200') {
      throw new Error('发送失败');
    }
  }

}

module.exports = UserService;
